package cn.jb698.codec.msm.generator.v5base.beans;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

import cn.jb698.codec.enums.ColumnHtmlTypeEnum;
import cn.jb698.codec.enums.ColumnQueryTypeEnum;
import cn.jb698.codec.enums.YesNoUnknownEnum;
import cn.jb698.codec.msm.generator.util.CodecCfgObjUtils;
import cn.jb698.codec.msm.generator.util.CodecGeneUtils;

/**
 * 
 * 增删改查配置-字段对象
 * 
 * @author LiuJianbin
 *
 */
public class BcrudCfgColumnObj {

    /**
     * 非必填字段Set
     */
    private static Set<String> notRequiureColumnSet = new HashSet<>(Arrays.stream(new String[] {"create_time","update_time"}).collect(Collectors.toList()))   ;

    /**
     * 新增非必填字段Set
     */
    private static Set<String> insertNotRequiredColumnSet = notRequiureColumnSet; // new HashSet<>(Arrays.stream(new String[] {"create_time","update_time"}).collect(Collectors.toList()))   ;
    
    /**
     * 修改非必填字段Set
     */
    private static Set<String> editNotRequiredColumnSet = notRequiureColumnSet; // new HashSet<>(Arrays.stream(new String[] {"create_time","update_time"}).collect(Collectors.toList()))   ;
    
    /**
     * 默认查询字段集
     */
    private static Set<String> queryColumnSet = new HashSet<>(Arrays.stream(new String[] {"create_time"}).collect(Collectors.toList()))   ;

//  基本字段信息 Start /////////////////////////////////////

    /**
     * 数据库字段隶属的实际表名称
     */
    private String tableName;

    /**
     * 数据库字段.
     */
    private String column;

    /**
     * 字段长度.
     */
    private Long columnLength;

    /**
     * 字段类型字符串 例: (BIT , TINYINT , INTEGER , SMALLINT ,) , (BIGINT ,) , ( DECIMAL ,
     * DOUBLE,FLOAT,REAL ,),(DATE,TIME,TIMESTAMP,),(CHAR,VARCHAR,TEXT,JSON), 等
     */
    private String columnType;

    /**
     * 字段类型表达式, 例: (BIT(2) , TINYINT(2) , INTEGER(20) , SMALLINT ,) , (BIGINT(20) ,)
     * , ( DECIMAL(10,2) , DOUBLE,FLOAT,REAL
     * ,),(DATE,TIME,TIMESTAMP,),(CHAR,VARCHAR,), 等
     */
    private String columnTypeExp;

    /**
     * 备注内容
     */
    private String comment;

    /**
     * 对应JDBC的数据类型,例: INTEGER,DECIMAL,VARCHAR,TEXT,DATE,DATETIME,TIMESTAMP,
     */
    private String jdbcType; // 

    /**
     * 是否自增,默认false
     */
    private Boolean isAutoIncrement = false;
    
    /**
     * 是否主键
     */
    private Boolean isPrimKey = false;
    

//  基本字段信息 End /////////////////////////////////////
    

    /**
     * 填入字符串的备注内容,如"abc" 转换后为: \"abc\" , 即值= comment.replaceAll("\"", "\\\\\"")
     */
    private String commentForStr;

    /**
     * 填入字符串的备注内容,如"abc" 转换后为: \"abc\" , 即值= comment.replaceAll("\"", "\\\\\"")
     */
    private String commentForComment;


    /**
     * 对应Java的数据类型,例: String,Integer,Long,Date,Double,BigDecimal等
     */
    private String javaType; 

    /**
     * 对应Golang的数据类型,例: int64 ,int32 ,int ,float64 ,string , time.Time
     */
    private String golangType; 

    /**
     * 字段对应的属性名
     */
    private String propName; 

    /**
     * 
     */
    private String propNameGetsetTail; // 字段对应的属性名的GET和SET尾部属性=propName的首字母大写

    /**
     * 字段表达式,自定义查询语句时使用.例: ( CASE t.columnName WHEN 1 THEN 'TRUE' ELSE 'FALSE' END ) AS tmp_column
     */
    private String columnExpress;

    /**
     * 对应字段的别名,自定义查询语句时使用.
     */
    private String columnAlias;

    /**
     * 字段表达式是否含有函数
     */
    private Boolean isExpressHaveFun;
    
    
// Ctrler层或前端专用属性 Start /////////////////////////////////// 
    
    /**
     * 标签名称,用于前端展示
     */
    private String labelName;
    
    /**
     * 是否必填(增必填),1是,其他值否
     */
    private Integer isRequired ;
    
    /**
     * (是否插入新增字段),1是,其他值否
     */
    private Integer isAdd ;
    
    /**
     * (是否允许编辑),1是,其他值否
     */
    private Integer isEdit ;
    
    /**
     * (是否列表行展示,RowVo),1是,其他值否
     */
    private Integer isList ;
    
    /**
     * (是否查询条件),1是,其他值否,默认主键和创建时间为查询条件
     */
    private Integer isQuery ;
    
    /**
     * (是否查询条件),1是,其他值否,默认主键和创建时间为查询条件
     */
    private String queryType;
    
    /**
     * html类型, input文本框 ,select下拉选择,radio唯一选择,editor富文本编辑器,datetime时间,date日期,
     */
    private String htmlType;

 // Ctrler层或前端专用属性 End ///////////////////////////////////

    public String getColumnType() {
        return columnType;
    }

    public void setColumnType(String columnType) {
        this.columnType = columnType;
    }

    public String getColumnAlias() {
        return columnAlias;
    }

    public void setColumnAlias(String columnAlias) {
        this.columnAlias = columnAlias;
    }

    public String getColumn() {
        return column;
    }

    public void setColumn(String column) {
        this.column = column;
    }

    public Long getColumnLength() {
        return columnLength;
    }

    public Boolean getIsPrimKey() {
        if(Objects.isNull(isPrimKey)) {
            isPrimKey = Boolean.FALSE;
        }
        return isPrimKey;
    }

    public BcrudCfgColumnObj setIsPrimKey(Boolean isPrim) {
        this.isPrimKey = isPrim;
        return this;
    }

    public String getCommentForStr() {
        if (this.commentForStr != null) {
            return this.commentForStr;
        } else if (this.comment != null) {
            this.commentForStr = CodecCfgObjUtils.parseCommentForStr(comment);
        }
        return this.commentForStr;
    }

    public void setCommentForStr(String commentForStr) {
        this.commentForStr = commentForStr;
    }

    public String getCommentForComment() {
        if (this.commentForComment != null) {
            return this.commentForComment;
        } else if (this.comment != null) {
            this.commentForComment = CodecCfgObjUtils.parseCommentForComment(comment);
        }
        return commentForComment;
    }

    public void setCommentForComment(String commentForComment) {
        this.commentForComment = commentForComment;
    }

    public void setColumnLength(Long columnLength) {
        this.columnLength = columnLength;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getPropName() {
        return propName;
    }

    public BcrudCfgColumnObj setPropName(String propName) {
        this.propName = propName;
        return this;
    }

    public String getPropNameGetsetTail() {
        if (propNameGetsetTail == null && propName != null) {
            propNameGetsetTail = propName.substring(0, 1).toUpperCase() + propName.substring(1);
        }
        return propNameGetsetTail;
    }

    public void setPropNameGetsetTail(String propNameGetsetTail) {
        this.propNameGetsetTail = propNameGetsetTail;
    }

    public String getJdbcType() {
        return jdbcType;
    }

    public void setJdbcType(String jdbcType) {
        this.jdbcType = jdbcType;
    }

    public String getJavaType() {
        return javaType;
    }

    public void setJavaType(String javaType) {
        this.javaType = javaType;
    }

    public String getColumnExpress() {
        return columnExpress;
    }

    public void setColumnExpress(String columnExpress) {
        this.columnExpress = columnExpress;
    }

    public Boolean getIsExpressHaveFun() {
        return isExpressHaveFun;
    }

    public void setIsExpressHaveFun(Boolean isExpressHaveFun) {
        this.isExpressHaveFun = isExpressHaveFun;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getGolangType() {
        return golangType;
    }

    public void setGolangType(String golangType) {
        this.golangType = golangType;
    }

    public String getColumnTypeExp() {
        return columnTypeExp;
    }

    public void setColumnTypeExp(String columnTypeExp) {
        this.columnTypeExp = columnTypeExp;
    }

    public Boolean getIsAutoIncrement() {
        return isAutoIncrement;
    }

    public void setIsAutoIncrement(Boolean isAutoIncrement) {
        this.isAutoIncrement = isAutoIncrement;
    }

    public String getLabelName() {
        if(Objects.isNull(labelName)) {
            String tmpComment = this.getComment();
            if(Objects.nonNull(tmpComment)) {
                labelName = CodecGeneUtils.calcColumnLabelName(tmpComment) ;
            }
        }
        return labelName;
    }

    public BcrudCfgColumnObj setLabelName(String labelName) {
        this.labelName = labelName;
        return this;
    }

    public Integer getIsRequired() {
        if(Objects.isNull(isRequired)) {
            String tmpColumn = this.getColumn();
            if(notRequiureColumnSet.contains(tmpColumn)) {
               isRequired = YesNoUnknownEnum.NO.getCode();
            }else {
                // 默认必填
                isRequired = YesNoUnknownEnum.YES.getCode();
            }
        }
        return isRequired;
    }

    public BcrudCfgColumnObj setIsRequired(Integer isRequired) {
        this.isRequired = isRequired;
        return this;
    }

    public Integer getIsAdd() {
        if(Objects.isNull(isAdd)) {
            String tmpColumn = this.getColumn();
            if(insertNotRequiredColumnSet.contains(tmpColumn)) {
                isAdd = YesNoUnknownEnum.NO.getCode();
            }else {
                // 默认必填
                isAdd = YesNoUnknownEnum.YES.getCode();
            }
        }
        return isAdd;
    }

    public BcrudCfgColumnObj setIsAdd(Integer isAdd) {
        this.isAdd = isAdd;
        return this;
    }

    public Integer getIsEdit() {
        if(Objects.isNull(isEdit)) {
            String tmpColumn = this.getColumn();
            if(editNotRequiredColumnSet.contains(tmpColumn)) {
                isEdit = YesNoUnknownEnum.NO.getCode();
            }else {
                // 默认必填
                isEdit = YesNoUnknownEnum.YES.getCode();
            }
        }
        return isEdit;
    }

    public BcrudCfgColumnObj setIsEdit(Integer isEdit) {
        this.isEdit = isEdit;
        return this;
    }

    public Integer getIsList() {
        if(Objects.isNull(isList)) {
            isList = YesNoUnknownEnum.YES.getCode(); 
        }
        return isList;
    }

    public BcrudCfgColumnObj setIsList(Integer isList) {
        this.isList = isList;
        return this;
    }

    public Integer getIsQuery() {

        if(Objects.isNull(isQuery)) {
            String tmpColumn = this.getColumn();
            Boolean tmpIsPrimKey = this.getIsPrimKey();
            if(queryColumnSet.contains(tmpColumn) || tmpIsPrimKey ) {
                isQuery = YesNoUnknownEnum.YES.getCode();
            }else {
                // 默认必填
                isQuery = YesNoUnknownEnum.NO.getCode();
            }
        }
        return isQuery;
    }

    public BcrudCfgColumnObj setIsQuery(Integer isQuery) {
        this.isQuery = isQuery;
        return this;
    }

    public String getQueryType() {
        if(StringUtils.isBlank(queryType)) {
            String tmpColumnType = this.getColumnType();
            ColumnQueryTypeEnum qtypeEnum = doCalcQueryTypeByColumnType(tmpColumnType);
            queryType = qtypeEnum.getCode();
        }
        return queryType;
    }
    public BcrudCfgColumnObj setQueryType(String queryType) {
        this.queryType = queryType;
        return this;
    }
    

    public String getHtmlType() {
        if (StringUtils.isBlank(htmlType)) {
            String columnType = this.getColumnType();
            ColumnHtmlTypeEnum calcHtmlType = doCalcHtmlTypeByColumnType(columnType);
            htmlType = calcHtmlType.getCode();
        }
        return htmlType;
    }

    public void setHtmlType(String htmlType) {
        this.htmlType = htmlType;
    }

    /**
     * 
     * @param tmpColumnType
     * @return
     */
    public static ColumnQueryTypeEnum doCalcQueryTypeByColumnType(String tmpColumnType) {
        ColumnQueryTypeEnum rtTypeEnum = ColumnQueryTypeEnum.EQ;
        if(Objects.isNull(tmpColumnType)) {
            return rtTypeEnum;
        }
        if (CodecCfgObjUtils.columnTypeName_DATE.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_TIME.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_DATETIME.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_TIMESTAMP.equals(tmpColumnType)
                ) {
            rtTypeEnum = ColumnQueryTypeEnum.BETWEEN;
        }
        return rtTypeEnum;
    }
    
    /**
     * 计算HTML类型
     * @param tmpColumnType
     * @return
     */
    public static ColumnHtmlTypeEnum doCalcHtmlTypeByColumnType(String tmpColumnType) {
        ColumnHtmlTypeEnum rtTypeEnum = ColumnHtmlTypeEnum.INPUT; // 默认输入框
        if (Objects.isNull(tmpColumnType)) {
            return rtTypeEnum;
        }
        if (CodecCfgObjUtils.columnTypeName_DATE.equals(tmpColumnType)) {
            rtTypeEnum = ColumnHtmlTypeEnum.DATE;
        } else if (CodecCfgObjUtils.columnTypeName_TIME.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_DATETIME.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_TIMESTAMP.equals(tmpColumnType)) {
            rtTypeEnum = ColumnHtmlTypeEnum.DATETIME;
        } else if (CodecCfgObjUtils.columnTypeName_TINYINT.equals(tmpColumnType) 
                || CodecCfgObjUtils.columnTypeName_SMALLINT.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_INTEGER.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_INT.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_BIGINT.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_DECIMAL.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_DOUBLE.equals(tmpColumnType)
                || CodecCfgObjUtils.columnTypeName_FLOAT.equals(tmpColumnType)) {
            rtTypeEnum = ColumnHtmlTypeEnum.NUMBER;
        } else if (CodecCfgObjUtils.columnTypeName_TEXT.equals(tmpColumnType)) {
            rtTypeEnum = ColumnHtmlTypeEnum.DOC;
        } else if (CodecCfgObjUtils.columnTypeName_JSON.equals(tmpColumnType)) {
            rtTypeEnum = ColumnHtmlTypeEnum.OBJ;
        }
        return rtTypeEnum;
    }


}
